射频识别(RFID)技术

实验:选卡操作

作者:陈广 日期:2019-2-18


实验目的

通过本实验,掌握 Mifare S50 卡的主动选卡以及被动选卡操作,单张卡片选卡以及多卡片选卡操作。

单张卡片的主动选卡

Mifare S50 是 ISO14443A 协议卡,此类型卡安全性较高,多用于公交车卡,银行卡,社保卡、消费卡。一般情况下,ISO14443 卡都是单张读取并操作。

在选择一个新的电子标签进行操作前,必须首先执行请求(Request)命令,为应对读写器上放有多张标签的情况,接下来要执行防冲突(Anticoll)命令,防冲突命令会返回多张标签中的一张的 UID 号,此时再进行选择(Select)此标签操作。

接下来我们编程进行选择一张卡片的操作。新建一个控制台应用程序,输入如下代码:

using System;
using System.Threading.Tasks;
using HBLib;
using HBLib.HR8002Reader;
using HBLib.ISO14443A;

namespace CmdDemo
{
    class Program
    {
        static ComPort com = new ComPort("COM3", 19200, 1000);

        static void Main(string[] args)
        {
            com.Open();
            Select();

            Console.ReadLine();
        }

        private static async Task Select()
        {   
            Reader reader = new Reader(0x00, com);
            I14443A i14443a = new I14443A(0x00, com);
            //请求操作
            await reader.ChangeToISO14443AAsync(); 
            var info = await i14443a.RequestAsync(RequestMode.AllCard);
            if (info.ReturnValue != ReturnMessage.Success)
            {
                Console.WriteLine(info.GetStatusStr());
                return;
            }
            //防冲突操作
            var info1 = await i14443a.AnticollAsync();
            if (info1.ReturnValue != ReturnMessage.Success)
            {
                Console.WriteLine(info1.GetStatusStr());
                return;
            }
            //选卡操作
            var info2 = await i14443a.SelectAsync(info1.UID);
            if(info2.ReturnValue==ReturnMessage.Success)
            {
                Console.WriteLine("选卡成功,选中卡片:" + info1.GetUIDStr() + "。卡片容量标志为:" + info2.Size.ToString());
            }
            else
            {
                Console.WriteLine(info1.GetStatusStr());
            }
        }
    }
}

运行程序,在读写器上不放卡片、放一张卡片、放多张卡片,运行程序,查看各自的效果。

思考题

这个系列文章,包括将来出的书中,会出现较多的思考题,你也可以理解为作业。我之前出的书,很多人会问我要习题答案,我当然会给。教书这么多年,我现在有了新的想法,至少在程序设计这一块,不应该有标准答案。我们更应注重培养的应当是解决问题的能力,将来工作时,遇到问题,不大可能会有人给你标准答案,很多的东西需要你自己摸索、解决。我自己就是这么过来的,在解决问题的过程中水平不断提高 。解决问题的能力是在不断痛苦折磨中锤炼出来的,给标准答案不会对这种重要的能力有任何帮助。我提出要求,只要你能按照要求完成,就是 100 分。至于你是怎么完成的,完成的质量如何,代码漂不漂亮,这些并不是最重要的,首先你要迈出这一步。最后一句话总结,将来我出的所有思考题都不会有任何答案。

下面我出一道思考题,让大家尝试一下:

思考题(难度 *):编写程序,每隔 5 秒钟进行一次选卡操作,如果选卡成功则蜂鸣器响一声。编写完成后在读写器上放 6 张卡片,看看是否能读取所有卡片。

被动选卡

什么是被动选卡呢?坐地铁刷卡就是被动选卡,当我们将地铁卡放到感应场,嘀一声,闸门打开,我们通过。当读写器感应到有卡片进入感应场,主动向上位机发出信号,这就是被动选卡。我们在上一个实验做的就是主动选卡:将卡片放到读写器,启动程序或点击上位机程序按钮,命令读写器读卡。HR8002 的命令只能由上位机发起,所以无法实现真正意义上的被动选卡。若要实现被动选卡功能,只能由上位机不停地向读写器发送选卡命令,当读写器返回选卡成功信息,则说明有标签进入感应场。

将程序更改如下:

static ComPort com = new ComPort("COM3", 19200, 1000);

static void Main(string[] args)
{
    com.Open();
    Select();

    Console.ReadLine();
}

private static async Task Select()
{
    Reader reader = new Reader(0x00, com);
    I14443A i14443a = new I14443A(0x00, com);
    string uidStr = "";
    await reader.ChangeToISO14443AAsync();
    while (true)
    {
        //请求操作
        var info = await i14443a.RequestAsync(RequestMode.AllCard);
        if (info.ReturnValue == ReturnMessage.Success)
        {
            //防冲突操作
            var info1 = await i14443a.AnticollAsync();
            if (info1.ReturnValue == ReturnMessage.Success)
            {
                //选卡操作
                var info2 = await i14443a.SelectAsync(info1.UID);
                if (info2.ReturnValue == ReturnMessage.Success)
                {
                    string uid = info1.GetUIDStr();
                    if (uidStr != uid)
                    {   //有新卡片进入感应场
                        uidStr = uid;
                        Console.WriteLine("选卡成功,选中卡片:" + uidStr + "。卡片容量标志为:" + info2.Size.ToString());
                        await reader.BeepAsync(5, 0, 1); //响一声
                    }
                }
            }
        }
        else
        {
            if (uidStr != "") //感应场内无卡
            {
                uidStr = "";
                Console.WriteLine("无卡");
            }
        }
        Thread.Sleep(300);
    }
}

运行程序,轮流放几张卡片进入然后离开感应场,程序运行结果如下。

选卡成功,选中卡片:8774DB2A。卡片容量标志为:8
无卡
选卡成功,选中卡片:47E0F62A。卡片容量标志为:8
无卡
选卡成功,选中卡片:8774DB2A。卡片容量标志为:8
无卡
选卡成功,选中卡片:8774DB2A。卡片容量标志为:8
无卡
选卡成功,选中卡片:47E0F62A。卡片容量标志为:8
无卡

当卡片进入感应场,选中此张卡片;当卡片离开感应场,显示无卡。基本实现我们平日所见的被动读卡功能。

思考题(难度 *):但此程序只是针对单张卡片进入感应场的情况,如果多张卡片进入感应场,则会不停地交替选中多张卡片。请更改程序,当多张卡片进入感应场时,只会选中其中一张卡片,且不会重复选择。

感应多张卡片

虽然 ISO14443A 卡一般情况下不会有同时读取多卡的需求。但做为学习者我们依然可以尝试实现这个功能。如果我们使用上一个程序来同时读取多张卡片,会发现大部分情况下只会读出 2 张卡片信息,有时会读出 3 张卡片信息。如果我在读写器上放了 6 张,甚至 10 张卡片,要求全部列出它们的卡号,该如何实现呢?我们可以每感应到一张卡片就将其置于休眠状态,以便可以读取其它卡片,直至所有卡片进入休眠状态。

为帮助大家理解这个过程,我做了一个 Demo(源码会随同 HBLib 库一起放在 GitHub),让大家以手动的方式感应多张卡片。

打开 Demo 程序,选择菜单项【RFID】➤【ISO14443A】➤【感应多张卡片】打开此程序,如下图所示:

图 1:上位机 Demo

前面 4 个命令我们之前都已经讲过,此程序多加了一个休眠命令。我们在读卡中放置 6 张以上卡片,此时我们以两种形式进行实验:

  1. 不使用休眠命令,看看可以选中多少张卡片。
  2. 借助休眠命令,按下图所示流程单击相应按钮进行选卡操作,看看可以选中多少张卡片。

图 1:多卡选择流程

我自己操作的结果是,如果在不移动卡片的情况下,很难将所有卡片选中。有时卡片休眠了,还可以被防冲突选择。总之在超过 2 张卡片的情况下读卡器不太稳定。同时也说明了 13.56MHz 并不适用于同时选中多张卡片的操作。

思考题(难度 ***):编写程序,显示感应场内所有标签的 UID,假设感应场内有 6 张标签,当感应完所有 6 标签后程序停止。完成时间越快,分数越高。

;

© 2018 - IOT小分队文章发布系统 v0.3